from . import course_blueprint
from ..utils.response_util import response
from ..utils.exception import APIException
from ..utils.error_code import *
from ..utils.check import *
from ..models import *

from flask import request, session
from sqlalchemy.exc import IntegrityError
import json
import xlrd
from math import ceil


@course_blueprint.route("/", methods=["GET", "POST"])
def main():
    return "Course"


@course_blueprint.errorhandler(APIException)
def error(e):
    return APIException.to_dict(e)


# @course_blueprint.route("/add", methods=["POST"])
# @user_is_login
# @check_user_type_3
# def course_add():
#     """
#     增加 course
#     :return:
#     """
#     data = request.json
#     username = session.get("username")
#     course_name = data.get("courseName")
#     course_teacher = data.get("courseTeacher")
#     chapter = data.get("chapter")
#     teach_class_list = list()
#
#     course = Course(course_name, json.dumps(chapter, ensure_ascii=False), username)
#
#     try:
#         db.session.add(course)
#         db.session.commit()
#     except IntegrityError:
#         db.session.rollback()
#         raise APIException(COURSE_ALREADY_EXISTS)
#     except Exception:
#         db.session.rollback()
#         raise APIException(ADD_ERROR)
#     course_id = course.course_id
#
#     for teacher in course_teacher:
#         user = User.query.filter_by(username=teacher).limit(1).first()
#         if user is None:
#             raise APIException(USERNAME_NOT_EXISTS)
#         teach_class = TeachClass(teacher, course_id)
#         teach_class_list.append(teach_class)
#     try:
#         db.session.add_all(teach_class_list)
#         db.session.commit()
#     except:
#         db.session.rollback()
#         raise APIException(ADD_ERROR)
#     finally:
#         db.session.close()
#
#     return response(200, "Add Course Success", {"course_id": course_id})
#


@course_blueprint.route("/delete", methods=["POST"])
@user_is_login
@check_user_type_3
def course_delete():
    """
    删除 course
    :return:
    """
    data = get_data()
    username = session.get("username")
    course_id = data.get("courseId")

    user = User.query.filter(User.username == username).limit(1).first()
    course = Course.query.filter(Course.course_id == course_id).first()
    if course is None:
        raise APIException(COURSE_NOT_EXISTS)
    if user.user_type == 3 and course.course_head_id != user.username:
        raise APIException(INSUFFICIENT_USER_PERMISSION)

    res = Course.query.filter_by(course_id=course_id).delete()
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(DELETE_ERROR)
    finally:
        db.session.close()

    if res == 1:
        return response(200, "Delete Course Success", {"course_id": course_id})
    else:
        raise APIException(DELETE_ERROR)


@course_blueprint.route("/list", methods=["POST"])
@user_is_login
def course_search():
    """
    查询 所选(所管理) course
    :return:
    """
    data = request.args
    username = session.get("username")
    try:
        current_page = int(data.get("currentPage"))
    except:
        current_page = 1
    data_per_page = 10
    r = list()
    sql = "SELECT count(*) FROM `student_course` WHERE course_id="

    user = User.query.filter(User.username == username).first()
    if user is None:
        raise APIException(USERNAME_NOT_EXISTS)
    # 查询者为学生: 查询所选课程
    if user.user_type == 1:
        student_course_list = StudentCourse.query.filter_by(student_id=username).order_by(-StudentCourse.create_time).all()
        if student_course_list is []:
            return response(609, "Query Course Success", {})
        list_len = len(student_course_list)
        for student_course in student_course_list:
            tmp = dict()
            course = Course.query.filter(Course.course_id == student_course.course_id).limit(1).first()
            tmp["courseId"] = student_course.course_id
            tmp["courseName"] = course.course_name
            tmp["courseHeadId"] = course.course_head_id
            tmp["score"] = student_course.score
            r.append(tmp)

    # 查询者为教师: 查询所授课的课程
    elif user.user_type == 2:
        teach_classes = TeachClass.query.filter(TeachClass.teacher_id == username).order_by(-TeachClass.create_time).all()
        list_len = len(teach_classes)
        for teach_class in teach_classes:
            tmp = dict()
            course = Course.query.filter(Course.course_id == teach_class.class_id).limit(1).first()
            course_num = db.session.execute(sql + str(course.course_id)).scalar()
            tmp["courseId"] = teach_class.class_id
            tmp["courseName"] = course.course_name
            tmp["courseHeadId"] = course.course_head_id
            tmp["courseStudentNum"] = course_num
            r.append(tmp)
    # 查询者为课程负责人: 查询所负责的课程
    elif user.user_type == 3:
        courses = Course.query.filter(Course.course_head_id == username).order_by(-Course.create_time).all()
        list_len = len(courses)
        for course in courses:
            tmp = dict()
            course_num = db.session.execute(sql + str(course.course_id)).scalar()
            tmp["courseId"] = course.course_id
            tmp["courseName"] = course.course_name
            tmp["courseHeadId"] = course.course_head_id
            tmp["courseStudentNum"] = course_num
            r.append(tmp)
        teach_classes = TeachClass.query.filter(TeachClass.teacher_id == username).all()
        for teach_class in teach_classes:
            tmp = dict()
            course = Course.query.filter(Course.course_id == teach_class.class_id).limit(1).first()
            course_num = db.session.execute(sql + str(course.course_id)).scalar()
            tmp["courseId"] = teach_class.class_id
            tmp["courseName"] = course.course_name
            tmp["courseHeadId"] = course.course_head_id
            tmp["courseStudentNum"] = course_num
            r.append(tmp)
    # 查询者为系统管理员: 查询所有课程
    elif user.user_type == 4:
        courses = Course.query.order_by(-Course.create_time).all()
        list_len = len(courses)
        for course in courses:
            course_num = db.session.execute(sql + str(course.course_id)).scalar()
            tmp = dict()
            tmp["courseId"] = course.course_id
            tmp["courseName"] = course.course_name
            tmp["courseHeadId"] = course.course_head_id
            tmp["courseStudentNum"] = course_num
            r.append(tmp)

    max_page_num = ceil(list_len / data_per_page)
    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }

    return response(200, "Query Course Success", ret)


@course_blueprint.route("/update", methods=["POST"])
@user_is_login
@check_user_type_3
def course_update():
    """
    更新 所管理 课程
    :return:
    """
    data = get_data()
    username = session.get("username")
    course_id = data.get("courseId")
    course_name = data.get("courseName")
    chapter = data.get("chapter")
    course_head_id = data.get("courseHeadId")
    course_teachers = data.get("courseTeacher")
    new_data = dict()

    user = User.query.filter(User.username == username).first()
    course = Course.query.filter(Course.course_id == course_id).first()
    if course is None:
        raise APIException(COURSE_NOT_EXISTS)
    head = course.course_head_id
    if head != int(username) and user.user_type < 4:
        raise APIException(INSUFFICIENT_USER_PERMISSION)

    if course_name != "" and course_name is not None:
        new_data["course_name"] = course_name
    if chapter != "" and chapter is not None:
        new_data["chapter"] = json.dumps(chapter, ensure_ascii=False)
    if user.user_type == 4 and course_head_id is not None:
        new_data["course_head_id"] = course_head_id
    res = Course.query.filter_by(course_id=course_id).update(new_data)
    if course_teachers is not None:
        TeachClass.query.filter(TeachClass.class_id == course_id).delete()
        teacher_list = []
        for teacher in course_teachers:
            teach_class = TeachClass(teacher, course_id)
            teacher_list.append(teach_class)
        try:
            db.session.add_all(teacher_list)
        except:
            db.session.rollback()
            raise APIException(UPDATE_ERROR)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(UPDATE_ERROR)
    finally:
        db.session.close()
    if res == 1:
        return response(200, "Update Course Success", {"courseId": course_id})
    else:
        raise APIException(UPDATE_ERROR)


@course_blueprint.route("/add", methods=["POST"])
@user_is_login
@check_user_type_2
def course_student_add():
    """
    添加班级学生
    :return:
    """
    data = get_data()
    student_id = data.get("studentId")
    username = session.get("username")
    course_name = data.get("courseName")
    course_teacher = data.get("courseTeacher")
    chapter = data.get("chapter")
    teach_class_list = list()

    course = Course(course_name, json.dumps(chapter, ensure_ascii=False), username)
    try:
        db.session.add(course)
        db.session.commit()
    except IntegrityError:
        db.session.rollback()
        raise APIException(COURSE_ALREADY_EXISTS)
    except Exception:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    course_id = course.course_id

    if course_teacher != []:
        for teacher in course_teacher:
            user = User.query.filter_by(username=teacher).limit(1).first()
            if user is None:
                raise APIException(USERNAME_NOT_EXISTS)
            teach_class = TeachClass(teacher, course_id)
            teach_class_list.append(teach_class)

    user = User.query.filter(User.username == username).limit(1).first()
    if user.user_type == 2:
        teach_class = TeachClass.query.filter(TeachClass.class_id == course_id, TeachClass.teacher_id == username)\
            .limit(1).first()
        if teach_class is None:
            raise APIException(INSUFFICIENT_USER_PERMISSION)
    student_course_list = []
    if student_id != [] and student_id is not None:
        for student in student_id:
            student_course = StudentCourse(student, course_id)
            student_course_list.append(student_course)
    try:
        db.session.add_all(student_course_list)
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(ADD_ERROR)
    finally:
        db.session.close()

    return response(200, "Add Course And Student Success", {})


@course_blueprint.route("/student/import", methods=["POST"])
@user_is_login
@check_user_type_2
def course_student_import():
    """
    通过文件导入 student 到 course
    :return:
    """
    data = get_data()
    username = session.get("username")
    course_id = data.get("courseId")

    user_list = []
    files = request.files.get("file", "")
    if files == "":
        students = data.get("students")
        for student in students:
            user = User.query.filter_by(username=student).limit(1).first()
            if user is None:
                raise APIException(USERNAME_NOT_EXISTS)
            student_course = StudentCourse(student, course_id)
            user_list.append(student_course)
            try:
                db.session.add_all(user_list)
                db.session.commit()
            except IntegrityError as e:
                raise APIException(USERNAME_ALREADY_EXISTS, {"username": e.args})
        return response(200, "Student Add To Course Success", {"length": len(user_list)})
    filename = files.filename
    suffix = filename.split(".")[-1]

    if suffix == "xlsx" or suffix == "xls":
        content = xlrd.open_workbook(file_contents=data.read())
        status = content.sheet_loaded(content.sheet_names()[0])

        if status:
            data = content.sheets()[0].col_values(0)
            if data == [] or data is None:
                raise APIException(NO_USERNAME)
            for student in data:
                user = User.query.filter(User.username == student).first()
                if user is None:
                    raise APIException(USERNAME_NOT_EXISTS)
                student_course = StudentCourse(student, course_id)
                user_list.append(student_course)
            try:
                db.session.add_all(user_list)
                db.session.commit()
            except IntegrityError as e:
                raise APIException(USERNAME_ALREADY_EXISTS, {"username": e.args})
    elif suffix == "csv":
        for student in data.readlines():
            user = User.query.filter(User.username == student).first()
            if user is None:
                raise APIException(USERNAME_NOT_EXISTS)
            student_course = StudentCourse(student, course_id)
            user_list.append(student_course)
        try:
            db.session.add_all(user_list)
            db.session.commit()
        except IntegrityError as e:
            raise APIException(USERNAME_ALREADY_EXISTS, {"username": e.args})
    else:
        raise APIException(ILLEGAL_FILE_FORMAT)

    db.session.close()

    return response(200, "Student Add To Course Success", {"length": len(user_list)})


@course_blueprint.route("/student/get", methods=["POST"])
@user_is_login
@check_user_type_2
def course_student_get():
    """
    获取 班级 所有 学生列表
    :return:
    """
    try:
        current_page = int(request.args.get("currentPage"))
    except:
        current_page = 1
    data = get_data()
    course_id = data.get("courseId")
    homeworks = Homework.query.filter(Homework.homework_course == course_id).order_by(-Homework.create_time).all()
    data_per_page = 10
    r = list()

    student_courses = StudentCourse.query.filter_by(course_id=course_id).order_by(-StudentCourse.create_time).all()
    list_len = len(student_courses)
    max_page_num = ceil(list_len / data_per_page)
    for student_course in student_courses:
        tmp = dict()
        student_id = student_course.student_id
        user = User.query.filter(User.username == student_id).limit(1).first()
        if user is not None:
            for i, homework in enumerate(homeworks):
                student_homework = StudentHomework.query.filter(StudentHomework.homework_id == homework.homework_id,
                                                                StudentHomework.student_id == student_id).limit(1).first()
                if student_homework is not None:
                    tmp["homework" + str(i+1)] = student_homework.score
                else:
                    tmp["homework" + str(i+1)] = "未完成"
            tmp["username"] = student_id
            tmp["nickname"] = user.nickname if user.nickname is not None else student_id
            tmp["score"] = student_course.score
        r.append(tmp)
    
    if r is []:
        raise APIException(USERNAME_NOT_EXISTS)
    ret = {
        "currentPage": current_page,
        "maxPageNum": max_page_num,
        "num": list_len,
        "list": r[data_per_page * (current_page - 1): data_per_page * current_page]
    }
    return response(200, "Query Course Student Success", ret)


@course_blueprint.route("/student/delete", methods=["POST"])
@user_is_login
@check_user_type_2
def course_student_delete():
    """
    删除 班级 指定学生
    :return:
    """
    data = get_data()
    course_id = data.get("courseId")
    student_id = data.get("studentId")

    res = StudentCourse.query.filter_by(course_id=course_id, student_id=student_id).delete()
    try:
        db.session.commit()
    except:
        db.session.rollback()
        raise APIException(DELETE_ERROR)
    finally:
        db.session.close()

    if res == 1:
        return response(200, "Delete Student Course Success", {})
    else:
        raise APIException(DELETE_ERROR)


@course_blueprint.route("/courseName/get", methods=["POST"])
@user_is_login
@check_user_type_2
def get_manage_course_name():
    """
    获取 所管理的课程名
    :return:
    """
    username = session.get("username")
    courses = list()
    r = list()

    user = User.query.filter_by(username=username).limit(1).first()
    # 教师
    if user.user_type == 2:
        classes = TeachClass.query.filter_by(teacher_id=username).all()
        for course in classes:
            class_id = course.class_id
            courses.append(Course.query.filter_by(course_id=class_id).limit(1).first())
    # 课程负责人
    elif user.user_type == 3:
        courses = Course.query.filter_by(course_head_id=int(username)).all()
    # 系统管理员
    elif user.user_type == 4:
        courses = Course.query.all()

    for course in courses:
        tmp = dict()
        tmp["courseName"] = course.course_name
        tmp["courseId"] = course.course_id
        r.append(tmp)

    return response(200, "Get Course Name Success", r)


@course_blueprint.route("/chapter/get", methods=["POST"])
@user_is_login
@check_user_type_2
def get_course_chapter_name():
    """
    获取课程所拥有的章节
    :return:
    """
    data = get_data()
    r = list()
    course_id = data.get("courseId")
    course = Course.query.filter_by(course_id=course_id).limit(1).first()
    if course is None:
        raise APIException(COURSE_NOT_EXISTS)
    chapter = json.loads(course.chapter)

    for single_chapter in chapter:
        for knowledge in single_chapter["chapterKnowledge"]:
            r.append(knowledge)

    return response(200, "Get Chapter Success", r)


@course_blueprint.route("/search", methods=["POST"])
@user_is_login
@check_user_type_2
def get_course_detail():
    """
    获取课程所有细节
    :return:
    """
    data = get_data()
    r = dict()
    course_id = data.get("courseId")
    course = Course.query.filter_by(course_id=course_id).limit(1).first()
    if course is None:
        raise APIException(COURSE_NOT_EXISTS)

    teachers = TeachClass.query.filter_by(class_id=course_id).all()
    r["courseTeacher"] = list()
    for teacher in teachers:
        tmp = dict()
        teacher_name = User.query.filter_by(username=teacher.teacher_id).limit(1).first()
        tmp["teacherId"] = teacher.teacher_id
        tmp["name"] = teacher_name.nickname if teacher_name.nickname is not None else teacher_name.username
        r["courseTeacher"].append(tmp)
    r["courseId"] = course.course_id
    r["courseName"] = course.course_name
    r["chapter"] = json.loads(course.chapter)
    r["courseHeadId"] = course.course_head_id

    return response(200, "Get Course Success", r)
